/**
 * Title:MainService.java
 * Description:
 * Date:2016年6月6日上午8:53:23
 * Author:wei.liang 
 * Version:V1.0
 */

package com.wz.datachannel.service;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;

import com.google.protobuf.ByteString;
import com.wizhong.localsvr.dp.ChannelErrorCode;
import com.wizhong.localsvr.server.TCPServerLink;
import com.wizhong.localsvr.server.TCPServerManager;
import com.wizhong.localsvr.server.TCPServerManager.NotServerException;
import com.wizhong.localsvr.server.TCPServerManager.OnTcpServerManagerEvent;
import com.wizhong.localsvr.server.TCPServerManager.ServerCloseException;
import com.wz.datachannel.R;
import com.wz.datachannel.app.AppContext;
import com.wz.datachannel.common.GlobalConstant;
import com.wz.datachannel.interfaces.OnWzDataChannelEvent;
import com.wz.datachannel.netty.WzDataChannelHelper;
import com.wz.datachannel.util.log4j.Log4jManager;
import com.wz.datachannel.view.UpdateActivity;
import com.wz.datachannel.view.UpdateStActivity;

import android.app.Notification;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.text.TextUtils;
import android.widget.RemoteViews;

/**
 * @Description
 * @author wei.liang
 * @Date 2016年6月6日上午8:53:23
 */
public class MainService extends Service {
	private Logger mLog = Log4jManager.getInstance();

	private WzDataChannelHelper mDataChannelHelper = null;
	private TCPServerManager mTcpServerManager = null;// 本地tcp server
	private Thread mLocalNetThd = null;
	private ConcurrentHashMap<Integer, IDataChannelCallBack> mMapNeedCallback = new ConcurrentHashMap<Integer, IDataChannelCallBack>();// key:serverCode，value：callback

	private static MainService mInstance;
	private static final int NOTIFY_ID = 1439;

	private boolean isSysShutDown = false;//true:系统关机

	public static MainService getInstance() {
		return mInstance;
	}

	public static WzDataChannelHelper getDataChannel() {
		if (mInstance == null)
			return null;
		return mInstance.mDataChannelHelper;
	}

	@Override
	public IBinder onBind(Intent intent) {
		mLog.debug("onBind");
		return mBinder;
	}

	@Override
	public void onCreate() {
		mLog.debug("onCreate");
		super.onCreate();

	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		mLog.debug("onStartCommand");
		if (null == mInstance) {
			mInstance = this;
			init();
		}
		return START_NOT_STICKY;
	}

	private synchronized void init() {
		//创建通知栏
		updateNotification(false);
		//初始化本地网络
		initLocalNet();
		//初始化Netty
		mDataChannelHelper = WzDataChannelHelper.getInstance(getApplication(), onWzDataChannelEvent);

		registerReceiver(mOrderReceiver, getOrderFilter());
	}

	private IntentFilter getOrderFilter() {
		IntentFilter filter = new IntentFilter();
		filter.addAction(Intent.ACTION_SHUTDOWN);
		return filter;
	}

	/**
	 * 有序广播接收
	 */
	private BroadcastReceiver mOrderReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (Intent.ACTION_SHUTDOWN.equals(action)) {//关机广播
				mLog.info("System ShutDown..");
				AppContext.getInstance().setShutDown(true);
				closeAllConn();
			}
		}
	};

	private void closeAllConn() {
		if (null != mTcpServerManager) {
			mTcpServerManager.deleteServerAll(ChannelErrorCode.ERROR_FALI_CODE_CONNECT_OFF, "通道服务断开");
			mTcpServerManager.stopListenr();
			mTcpServerManager = null;
		}
		if (null != mDataChannelHelper) {
			mDataChannelHelper.onDestory();
			mDataChannelHelper = null;
		}
	}

	@Override
	public void onDestroy() {
		mLog.debug("onDestroy");
		super.onDestroy();
		unregisterReceiver(mOrderReceiver);
		stopForeground(true);
		closeAllConn();
	}

	/**
	 * 初始化本地网络通道
	 * @author wei
	 */
	private void initLocalNet() {
		if (null == mLocalNetThd && null == mTcpServerManager) {
			mLocalNetThd = new Thread() {
				public void run() {
					// 建立本地tcpserver
					mTcpServerManager = new TCPServerManager();
					mTcpServerManager.setOnTcpServerManagerEvent(mTcpSerManageEvent);
					mTcpServerManager.startListenr("127.0.0.1", 0);
					int port = mTcpServerManager.getListenrPort();
					Iterator<Map.Entry<Integer, IDataChannelCallBack>> list = mMapNeedCallback.entrySet().iterator();
					while (list.hasNext()) {//回调通知
						Map.Entry<Integer, IDataChannelCallBack> lk = list.next();
						Integer serverCode = lk.getKey();
						IDataChannelCallBack cb = lk.getValue();
						String token = mTcpServerManager.createNewToken(serverCode, "");
						if (TextUtils.isEmpty(token)) {
							onGetTokenFailed(cb, ChannelErrorCode.ERROR_EXCEPTION_CODE_ACCOUNT_ALREADY_CONNECTED, "无法重复连接通道");
						} else {
							onGetTokenSucceed(cb, token, port);
						}
						list.remove();
					}
				}
			};
			mLocalNetThd.start();
		}
	}

	private IDataChannelService.Stub mBinder = new IDataChannelService.Stub() {

		@Override
		public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
			try {
				super.onTransact(code, data, reply, flags);
			} catch (RuntimeException e) {
				mLog.info("Unexpected remote exception", e);
				throw e;
			}
			return true;
		}

		@Override
		public void init(final int serverCode, final IDataChannelCallBack icallback) {
			if (null == icallback) {// callback不允许为null
				return;
			}
			if (AppContext.getInstance().isShutDown()) {
				mLog.error("已关机，不再受理登录请求");
			} else if (PackageManager.PERMISSION_DENIED == checkCallingPermission(GlobalConstant.PERMISSION_DATA_CHANNEL)) {// 应用没有该权限
				mLog.error("refuse unknown app apply bind");
				onGetTokenFailed(icallback, ChannelErrorCode.ERROR_EXCEPTION_CODE_APP_NO_PERMISSION, "应用无权限连接通道服务");
			} else {
				getTokenPort(serverCode, icallback);
			}
		}
	};

	/**
	 * 获取token 和端口号  
	 * @author wei.liang 
	 * @param serverCode
	 * @param icallback
	 * @return
	 */
	public void getTokenPort(int serverCode, IDataChannelCallBack icallback) {
		if (null == mTcpServerManager || !mTcpServerManager.isListenrRun()) {
			mMapNeedCallback.put(serverCode, icallback);
			initLocalNet();
		} else {// 本地tcp已建立
			String token = mTcpServerManager.createNewToken(serverCode, "");
			if (TextUtils.isEmpty(token)) {
				onGetTokenFailed(icallback, ChannelErrorCode.ERROR_EXCEPTION_CODE_ACCOUNT_ALREADY_CONNECTED, "无法重复连接通道服务");
			} else {
				onGetTokenSucceed(icallback, token, mTcpServerManager.getListenrPort());
			}
		}
	}

	private void onGetTokenFailed(IDataChannelCallBack icallback, int errCode, String errmsg) {
		try {
			icallback.onGetTokenPortFailed(errCode, errmsg);
		} catch (Exception e) {
		}
	}

	private void onGetTokenSucceed(IDataChannelCallBack icallback, String token, int port) {
		try {
			icallback.onGetTokenPortSucceed(token, port);
		} catch (Exception e) {
		}
	}

	/**
	 * 本地tcp Server 回调事件
	 */
	OnTcpServerManagerEvent mTcpSerManageEvent = new OnTcpServerManagerEvent() {

		@Override
		public void OnServerStop() {
			mLog.debug("OnTcpServerStop");
		}

		@Override
		public void OnRequestLoginOut(Integer serverCode, TCPServerLink arg1) {
			mLog.debug("OnRequestLoginOut," + serverCode);
			if (null != mDataChannelHelper) {
				mDataChannelHelper.logoutBusiness(serverCode);
			}
		}

		@Override
		public void OnRequestLogin(Integer serverCode, TCPServerLink arg1) {
			mLog.debug("OnRequestLogin," + serverCode);
			if (null == mDataChannelHelper) {
				mDataChannelHelper = WzDataChannelHelper.getInstance(getApplication(), onWzDataChannelEvent);
			}
			mDataChannelHelper.login(serverCode);
		}

		@Override
		public void OnReciveRoadData(Integer serverCode, byte[] data, TCPServerLink arg2) {
			mLog.debug("OnReciveRoadData,serverCode:" + serverCode + ",value:" + new String(data));
			if (null != mDataChannelHelper) {
				mDataChannelHelper.sendRoadData(serverCode, ByteString.copyFrom(data));
			}
		}

		@Override
		public void OnUpdateUserInfo(TCPServerLink link) {
			modiftyUserInfo();
		}
	};

	//======netty网络通道服务回调=====
	OnWzDataChannelEvent onWzDataChannelEvent = new OnWzDataChannelEvent() {

		@Override
		public void onRcvRoadData(Integer serverCode, ByteString data) {
			mLog.debug("rcvNettyRoadData," + serverCode + ":" + data.toStringUtf8());
			if (null != mTcpServerManager) {
				try {
					byte[] bytes = null;
					try {
						bytes = data.toByteArray();
					} catch (Exception e) {
					}
					mTcpServerManager.sendRoadData(serverCode, bytes);
				} catch (NotServerException e) {
					e.printStackTrace();
					if (null != mDataChannelHelper) {
						mDataChannelHelper.logoutBusiness(serverCode);
					}
				} catch (ServerCloseException e) {
					e.printStackTrace();
					if (null != mDataChannelHelper) {
						mDataChannelHelper.logoutBusiness(serverCode);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		@Override
		public void onLoginSucceed(Integer serverCode, String userInfo) {
			if (null != mTcpServerManager) {
				try {
					mTcpServerManager.loginServerScuess(serverCode, userInfo);
				} catch (NotServerException e) {
					e.printStackTrace();
					if (null != mDataChannelHelper) {
						mDataChannelHelper.logoutBusiness(serverCode);
					}
				}
			}
		}

		@Override
		public void onLoginFailed(Integer serverCode, int errCode, String errInfo) {
			if (null != mTcpServerManager) {
				try {
					mTcpServerManager.loginServerError(serverCode, errCode, errInfo);
				} catch (NotServerException e) {
					e.printStackTrace();
					if (null != mDataChannelHelper) {
						mDataChannelHelper.logoutBusiness(serverCode);
					}
				}
			}
		}

		@Override
		public void onLogoutResult(Integer serverCode, int resultCode, String msg) {
			if (null != mTcpServerManager) {
				mTcpServerManager.deleteServer(serverCode, resultCode, msg);
			}
		}

		@Override
		public void onDataChannelOpen() {
			if (null != mTcpServerManager) {
				mTcpServerManager.setWizhongDataNetConnected();
			}
			updateNotification(true);
		}

		@Override
		public void onDataChannelClose(int errCode, String msg) {
			if (null != mTcpServerManager) {
				mTcpServerManager.deleteServerAll(errCode, msg);
			}
			updateNotification(false);
		}

		@Override
		public void onRcvUpdateUserInfo(String userInfo) {
			if (null != mTcpServerManager) {
				mTcpServerManager.updateUserInfoAll(userInfo);
			}
		}

	};

	//=======notification=============	
	private Notification mNtf = null;
	private RemoteViews mRemoteView = null;

	/**
	 * 更新显示notification
	 * @author wei 
	 * @param isLogin
	 */
	private void updateNotification(boolean isLogin) {
		if (null == mRemoteView) {
			mRemoteView = new RemoteViews(getPackageName(), R.layout.notification_view);
		}
		mRemoteView.setTextViewText(R.id.ntf_status_tv, isLogin ? "已连接" : "已断开");
		if (null == mNtf) {
			mNtf = new Notification();
			mNtf.contentView = mRemoteView;
			mNtf.flags |= Notification.FLAG_ONGOING_EVENT;
			mNtf.icon = R.drawable.icon;
		}
		startForeground(NOTIFY_ID, mNtf);
	}

	///======修改用户信息=======
	/**
	 * 修改用户信息
	 */
	public void modiftyUserInfo() {
		try {
			Intent intent = new Intent();
			intent.setClass(MainService.this, UpdateStActivity.class);
			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
			startActivity(intent);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//=====状态====
	enum SyncStatus {
		wait, exeu,
	}

	class ThreadNtf {
		private SyncStatus status;

		public ThreadNtf() {
			setStatus(SyncStatus.exeu);
		}

		public SyncStatus getStatus() {
			return status;
		}

		public void setStatus(SyncStatus status) {
			this.status = status;
		}
	}
}
